#include "mic_app.h"
#include "audio_encoder.h"
#include "audio_decoder.h"
#include "driver_i2s.h"
#include "driver_codec.h"
#include "driver_uart.h"
#include "driver_pmu.h"
#include "driver_gpio.h"
	#include "os_task.h"
#include "os_mem.h"

enum{
	MIC_STATUS  = 0,
	PLAY_STATUS = 1,
	NONE_STATUS = 2,
};
volatile uint8_t current_status = NONE_STATUS;



void set_status(uint8_t status)
{
	current_status = status;
}

void audio_mic_init(void)
{
		//pmu_codec_power_enable();
		//codec_init(CODEC_SAMPLE_RATE_8000);
    

//    i2s_init(I2S_DIR_RX,8000,1);    //8,16,32,48
	  //codec_enable_adc();
	
	
		//audio_speaker_codec_init();	
		//i2s_init(I2S_DIR_TX,8000,1);	
		//codec_enable_dac();
		//codec_disable_adc();
	  //codec_disable_dac();

	
	

	
    //NVIC_SetPriority(I2S_IRQn, 2);
	
	//ENABLE PA
	system_set_port_mux(GPIO_PORT_A, GPIO_BIT_1, PORTA1_FUNC_A1);
	system_set_port_pull(GPIO_PA1, true);
	gpio_set_dir(GPIO_PORT_A, GPIO_BIT_1, GPIO_DIR_OUT);
	gpio_porta_write(gpio_porta_read() | (1<<GPIO_BIT_1) );
	
	
	  //audio_mic_stop();
	
		//audio_mic_start();
}

 void audio_mic_start(void)
{
	  NVIC_DisableIRQ(I2S_IRQn);
	  current_status = MIC_STATUS;
	  ringbuffer_reset();
		
		pmu_codec_power_enable();
	
	  codec_init(CODEC_SAMPLE_RATE_8000);
	  i2s_init(I2S_DIR_RX,8000,1);    //8,16,32,48
	
		codec_enable_adc();
	  codec_disable_dac();
	
	
		
   i2s_int_enble_or_disable(I2S_DIR_RX,true);
	 i2s_int_enble_or_disable(I2S_DIR_TX,false);
	
	
	  i2s_start();
    NVIC_EnableIRQ(I2S_IRQn);
	
		
}

 void audio_mic_stop(void)
{
		current_status = NONE_STATUS;
		//ringbuffer_reset();
		NVIC_DisableIRQ(I2S_IRQn);
    i2s_stop();
	
	  i2s_int_enble_or_disable(I2S_DIR_RX,false);
	  i2s_int_enble_or_disable(I2S_DIR_TX,false);
	
    codec_disable_adc();
    pmu_codec_power_disable();
		
}


void audio_speak_start()
{
	  NVIC_DisableIRQ(I2S_IRQn);
		current_status = PLAY_STATUS;
	  ringbuffer_reset();
		
		pmu_codec_power_enable();
	
		audio_speaker_codec_init();	
	  i2s_init(I2S_DIR_TX,8000,1);    //8,16,32,48
		codec_enable_dac();
	  NVIC_SetPriority(I2S_IRQn, 2);
	
	
		//codec_init(CODEC_SAMPLE_RATE_8000);
 
	  //codec_enable_adc();
		//
	
	
		//codec_disable_adc();
	
	  //i2s_int_enble_or_disable(I2S_DIR_RX,false);
	  //i2s_int_enble_or_disable(I2S_DIR_TX,true);
	  i2s_start();
		
	
    NVIC_EnableIRQ(I2S_IRQn);


}

void audio_speak_stop()
{
	  current_status = NONE_STATUS;
	  //ringbuffer_reset();
	  codec_disable_dac();
	  NVIC_DisableIRQ(I2S_IRQn);

		//i2s_int_enble_or_disable(I2S_DIR_RX,false);
	  //i2s_int_enble_or_disable(I2S_DIR_TX,false);
   
    i2s_stop();
		codec_disable_dac();
	  pmu_codec_power_disable();
		
}


/*********************************************************************
 * @fn		i2s_isr_ram
 *
 * @brief	I2S interrupt handler
 *
 * @param	None
 *
 * @return	None.
 */

bool is_write =false;
bool is_encode =false;
bool is_decode =false;
__attribute__((section("ram_code"))) void i2s_isr_ram(void)
{
 		//gpio_set_pin_value(GPIO_PORT_D, GPIO_BIT_7, 0);
		//gpio_set_pin_value(GPIO_PORT_D, GPIO_BIT_6, 1);
		uint16_t i2s_adc_data[I2S_FIFO_DEPTH/2]={0};
	  	
		if(1)
		if(current_status == MIC_STATUS)
		{	
			
				if((i2s_reg->status.rx_half_full)/*&&(i2s_reg->mask.rx_half_full)*/) {//codec_ADC
						//printf("M");
							int buffer_size = 0;
							buffer_size = get_audio_encoder_valid_size();
							is_encode = get_audio_encoder_is_busy();
						
							//is_encode = get_num_audio_encoder_is_busy(0);
							//is_encode1 = get_num_audio_encoder_is_busy(1);
						

							if(buffer_size>=AUDIO_FRAME_LEN)
							{
								if(is_encode == false)
								{
									//co_printf("send event\r\n");
									os_event_t event={0};
									event.event_id = ENCODER_EVENT;
									event.src_task_id = TASK_ID_NONE;
									event.param = NULL;
									event.param_len = 0;
									os_msg_post(task_id_audio_encode,&event);
								//msg_post_encode_handler();
								}	
							}
						
						
						for(uint32_t i=0; i<(I2S_FIFO_DEPTH/2); i++) {
								 i2s_adc_data[i] = i2s_reg->data;
								 //co_printf("%02x",i2s_adc_data[i] );
							}
					
							//if(current_status == MIC_STATUS)
							{
								is_write = audio_encoder_src_input((uint8_t *)i2s_adc_data,I2S_FIFO_DEPTH);
								audio_encode_current_frame_add();
							}

			
						
						}
				
						
					}
		else if(current_status == PLAY_STATUS)
		{	
		//printf("L");
					//if(i2s_reg->status.tx_half_empty)
					if((i2s_reg->status.tx_half_empty)&&(i2s_reg->mask.tx_half_empty))//codec_DAC
					{
						//printf("L");
							if(current_status == PLAY_STATUS)
					{
									//printf("1");
//								uint16_t len =  get_speak_len();//get_audio_encoder_valid_size();
//							  //printf("%d",len);
//								//if(len>=(64*10))
//								{
//									  printf("2");
//										//memset(i2s_adc_data,0x00,sizeof(i2s_adc_data));
//										int read_len  = audio_read_to_ringbuffer((char*)i2s_adc_data,AUDIO_FRAME_LEN);
//									
//											read_len=read_len/2;
//									for(uint32_t i=0; i<(read_len>=32?(I2S_FIFO_DEPTH/2):read_len); i++)
//									{
//											i2s_reg->data = i2s_adc_data[i];
//									}
//								
//								}
								
//								else
//								{
//										for(uint32_t i=0; i<(I2S_FIFO_DEPTH/2); i++)
//									{
//											i2s_reg->data = 0x00;
//									}
//								}
								
//								else
								{
									//printf("3");
										//memset(i2s_adc_data,0x00,sizeof(i2s_adc_data));
										//audio_read_to_ringbuffer((char*)i2s_adc_data,AUDIO_FRAME_LEN);
									
									int buffer_size = 0;
									buffer_size = get_audio_decoder_valid_size();
									
									is_decode = get_audio_decoder_is_busy();
										
											if(buffer_size>=AUDIO_FRAME_LEN)
									{
										if(is_decode == false)
										{
											msg_post_decode_handler();
										}
										
									}
									
									audio_read_decode_ringbuffer_len((char*)i2s_adc_data,AUDIO_FRAME_LEN);
										for(uint32_t i=0; i<(I2S_FIFO_DEPTH/2); i++)
									{
											i2s_reg->data = i2s_adc_data[i];
									}
								
								}
						
					}
						
				}
					
				
			}

				
		
			
			
					//gpio_set_pin_value(GPIO_PORT_D, GPIO_BIT_7, 1);
					//gpio_set_pin_value(GPIO_PORT_D, GPIO_BIT_6, 0);
}